package ChannelTutorial.Demo01;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

/**
 * Demo01 - Channel 基础概念演示 - 服务端
 * 
 * 学习目标：
 * 1. 理解 NioServerSocketChannel 的作用
 * 2. 学习如何创建和使用服务端 Channel
 * 3. 了解 Channel 的基本属性和方法
 */
@Slf4j
public class Server {

    public static void main(String[] args) {
        log.info("=== Channel 基础概念演示 - 服务端 ===\n");
        
        try {
            startServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 服务端：使用 NioServerSocketChannel
     * 
     * NioServerSocketChannel 的特点：
     * - 服务端监听 Channel
     * - 不传输数据，只负责接受客户端连接
     * - 每接受一个连接，会创建一个 NioSocketChannel
     */
    private static void startServer() throws Exception {
        EventLoopGroup boss = new NioEventLoopGroup(1);   // 处理连接
        EventLoopGroup worker = new NioEventLoopGroup();  // 处理 I/O

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class)  // 指定服务端 Channel 类型
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            log.info("服务端：新连接建立");

                            // 打印 Channel 的基本信息
                            printChannelInfo("服务端 Channel", ch);

                            // 添加处理器
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new ServerHandler());
                        }
                    });
            
            // bind() 方法会创建并初始化 NioServerSocketChannel
            ChannelFuture bindFuture = serverBootstrap.bind(8080).sync();
            log.info("服务端：已绑定端口 8080，等待客户端连接...\n");
            
            // 获取服务端 Channel
            Channel serverChannel = bindFuture.channel();
            printChannelInfo("服务端监听 Channel", serverChannel);
            
            // 等待服务端关闭
            bindFuture.channel().closeFuture().sync();
            
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    /**
     * 打印 Channel 的基本信息
     */
    private static void printChannelInfo(String name, Channel channel) {
        log.info("┌─────────────────────────────────────────");
        log.info("│ {} 信息：", name);
        log.info("│ Channel 类型: {}", channel.getClass().getSimpleName());
        log.info("│ Channel ID: {}", channel.id().asShortText());
        log.info("│ 本地地址: {}", channel.localAddress());
        log.info("│ 远程地址: {}", channel.remoteAddress());
        log.info("│ 是否激活(active): {}", channel.isActive());
        log.info("│ 是否打开(open): {}", channel.isOpen());
        log.info("│ 是否可写(writable): {}", channel.isWritable());
        log.info("│ 是否已注册(registered): {}", channel.isRegistered());
        log.info("└─────────────────────────────────────────\n");
    }

    /**
     * 服务端处理器
     */
    static class ServerHandler extends ChannelInboundHandlerAdapter {
        
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            String message = (String) msg;
            log.info("服务端收到消息: {}", message);
            
            // 回复客户端
            ctx.writeAndFlush("服务端收到: " + message);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error("服务端异常：", cause);
            ctx.close();
        }
    }
}

/*
=== 运行结果分析 ===

1. NioServerSocketChannel：
   - 服务端监听 Channel，只负责接受连接
   - 不传输实际数据
   - 绑定在指定端口上

2. Channel 的核心属性：
   - id：唯一标识
   - localAddress：本地地址
   - remoteAddress：远程地址
   - active：是否激活
   - open：是否打开
   - writable：是否可写

=== 关键知识点 ===

1. Channel 是网络连接的抽象
2. 服务端使用 NioServerSocketChannel 监听连接
3. 每个 Channel 都有唯一的 ID 和地址信息
4. Channel 提供了丰富的方法来操作网络连接
*/

